Socket
Must be included via require
. This library is not available in WASM builds of Pluto.
socket.connect
Establishes a TCP connection.
Parameters
- The host to connect to. Either an IPv4 or IPv6 address, or a domain name resolving to one.
- The port to contact the host on.
Returns
A socket instance on success. Nil on failure.
Multitasking
If called inside of a coroutine, this function yields. Otherwise, it blocks.
socket.listen
Creates a new listener for the given port.
Parameters
- The port to listen on.
Returns
A listener instance on success. Nil on failure.
socket.bind
A convenience function that wraps socket.listen
, automatically accepting new clients and spinning up a coroutine for them.
Parameters
- A scheduler instance.
- The port to listen on.
- The callback function that will be called in a new coroutine for each client socket.
pluto
local { scheduler, socket } = require "*"local sched = new scheduler()socket.bind(sched, 80, |s| -> dolocal content = "Hello, world!"s:send("HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-Length: "..#content.."\r\n\r\n"..content)end)sched:run()
Socket Class
Socket instances are obtained by calling socket.connect
(client), or from a listener (server).
socket.send
Sends data on a socket.
Parameters
- The socket instance.
- The data to send.
socket.recv
Receive data from a socket.
Parameters
- The socket instance.
Returns
- If the socket is open: The oldest chunk of data received on the transport layer (TCP packet) or crypto layer (TLS record) as a string.
- If the socket is closed: Nil.
Multitasking
If a message is buffered, the function can return immediately. If not, it will yield if inside a coroutine, and block otherwise.
pluto
local socket = require "pluto:socket"local s = socket.connect("google.com", 80)s:send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")print(s:recv())
socket.peek
Look at received data without consuming it.
Parameters
- The socket instances.
Returns
Either the string that would be returned next by socket.recv
or nothing if there is no message in the receive buffer.
socket.unrecv
Pushes a chunk of data to the front of the receive buffer, making it oldest for the purposes of socket.recv
.
Parameters
- The socket instance.
- The data to push.
pluto
local socket = require "pluto:socket"local sock = socket.connect("google.com", 80)sock:unrecv("World")sock:unrecv("Hello")print(sock:recv()) --> Helloprint(sock:recv()) --> World
socket.starttls
Attempts to add the TLS crypto layer to the socket, making the transport layer a sole carrier for TLS traffic.
Parameters (Client)
- The socket instance.
- The host name of the intended remote. This may be the same as what was passed to
socket.connect
. This name must be on the certificate that the remote will send.
Parameters (Server)
- The socket instance.
- An array of tables describing available certificates. Each certificate needs a
chain
andprivate_key
field, which should be a string containing valid PEM. Theprivate_key
must be RSA.
Returns
True on success. On failure, returns false and the socket is closed. If the socket is already using TLS, returns nil.
Multitasking
If called inside of a coroutine, this function yields. Otherwise, it blocks.
Client Examplepluto
local socket = require "pluto:socket"local s = socket.connect("pluto-lang.org", 443)assert(s:starttls("pluto-lang.org"), "Failed to establish secure connection.")s:send("GET / HTTP/1.1\r\nHost: pluto-lang.org\r\nConnection: close\r\n\r\n")while data := s:recv() doprint(data)end
Server Examplepluto
local { http, scheduler, socket } = require "*"local certs = {{chain = http.request("https://tls.cat/certs/viatls-2024/cert.pem"),private_key = http.request("https://tls.cat/certs/viatls-2024/key.pem"),}}local sched = new scheduler()socket.bind(sched, 443, |s| -> doif s:starttls(certs) thenlocal content = "Hello, world!"s:send("HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-Length: "..#content.."\r\n\r\n"..content)endend)print("https://127-0-0-1.viatls.com/")sched:run()
socket.close
Closes a socket.
Parameters
- The socket instance.
socket.getpeer
Get information about the other end of a connection.
Parameters
- The socket instance.
Returns
- The IP address as a string.
- The port.
pluto
local sock = require"socket".connect("1.1.1.1", 443)local ip, port = sock:getpeer()print(ip) --> 1.1.1.1print(port) --> 443
socket.getside
Get which side of the connection a socket is.
Parameters
- The socket instance.
Returns
Either "client" or "server".
pluto
local sock = require"socket".connect("1.1.1.1", 443)print(sock:getside()) --> client
socket.istls
Check if a connection is encrypted.
Parameters
- The socket instance.
pluto
local sock = require"socket".connect("1.1.1.1", 443)print(sock:istls()) --> falseassert(sock:starttls("1.1.1.1"))print(sock:istls()) --> true
socket.isopen
Check if a connection is still open.
Parameters
- The socket instance.
pluto
local sock = require"socket".connect("1.1.1.1", 443)print(sock:isopen()) --> truesock:close()print(sock:isopen()) --> false
Listener Class
Listener instances are obtained by calling socket.listen
.
accept
Accepts an incoming client connection, waiting until there is one.
Returns
A new socket instance. The socket can be used as per usual, with the exception of the starttls function being unavailable.
Multitasking
- If there is an incoming client connection, this function returns immediately.
- If there is not, it waits for one. Waiting means yielding if called inside a coroutine, and blocking otherwise.
hasconnection
Checks if there is an incoming client connection. If this function returns true, the next call to accept
is guaranteed not to block or yield.
pluto
local socket = require "pluto:socket"local l = socket.listen(80) or error("Failed to bind TCP/80")while not l:hasconnection() do -- Visit http://localhost to break this loopos.sleep(1)endprint(l:accept():recv())